package com.huawang.mdesign.model.service.constant.mindmap;

import com.huawang.core.definition.mof.UMLDefinitionConstants;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.stream.Stream;

/**
 * @author admin
 */

@Getter
@AllArgsConstructor
public enum RelationshipEnum {

    ASSOCIATION(0, UMLDefinitionConstants.Association, null),
    GENERALIZATION(1, UMLDefinitionConstants.Generalization, null),
    CONTAINS(2, UMLDefinitionConstants.Element_owner, null),
    TRANSITION(3, UMLDefinitionConstants.Transition, null),
    CONTROL_FLOW(4, UMLDefinitionConstants.ControlFlow, null),
    OBJECT_FLOW(5, UMLDefinitionConstants.ObjectFlow, null),
    CONNECTOR(6, UMLDefinitionConstants.Connector, null),
    BINDING_CONNECTOR(7, UMLDefinitionConstants.Connector, Collections.singletonList(UMLDefinitionConstants.SysML_BindingConnector)),
    SATISFY(8, UMLDefinitionConstants.Abstraction, Collections.singletonList(UMLDefinitionConstants.SysML_Satisfy)),
    DERIVE(9, UMLDefinitionConstants.Abstraction, Collections.singletonList(UMLDefinitionConstants.SysML_DeriveReqt)),
    COPY(10, UMLDefinitionConstants.Abstraction, Collections.singletonList(UMLDefinitionConstants.SysML_Copy)),
    TRACE(11, UMLDefinitionConstants.Abstraction, Collections.singletonList(UMLDefinitionConstants.SysML_Trace)),
    VERIFY(12, UMLDefinitionConstants.Abstraction, Collections.singletonList(UMLDefinitionConstants.SysML_Verify)),
    REFINE(13, UMLDefinitionConstants.Abstraction, Collections.singletonList(UMLDefinitionConstants.SysML_Refine)),
    ARBITRARY_CONNECTOR(14, UMLDefinitionConstants.Dependency, Collections.singletonList(UMLDefinitionConstants.UAF_ArbitraryConnector)),
    OPERATIONAL_CONTROL_FLOW(15, UMLDefinitionConstants.ControlFlow, Collections.singletonList(UMLDefinitionConstants.UAF_OperationalControlFlow)),
    OPERATIONAL_OBJECT_FLOW(16, UMLDefinitionConstants.ObjectFlow, Collections.singletonList(UMLDefinitionConstants.UAF_OperationalObjectFlow)),
    OPERATIONAL_CONNECTOR(17, UMLDefinitionConstants.Connector, Collections.singletonList(UMLDefinitionConstants.UAF_OperationalConnector)),
    RESOURCE_CONNECTOR(18, UMLDefinitionConstants.Connector, Collections.singletonList(UMLDefinitionConstants.UAF_ResourceConnector)),
    FUNCTION_CONTROL_FLOW(19, UMLDefinitionConstants.ControlFlow, Collections.singletonList(UMLDefinitionConstants.UAF_FunctionControlFlow)),
    FUNCTION_OBJECT_FLOW(20, UMLDefinitionConstants.ObjectFlow, Collections.singletonList(UMLDefinitionConstants.UAF_FunctionObjectFlow)),
    SERVICE_CONNECTOR(21, UMLDefinitionConstants.Connector, Collections.singletonList(UMLDefinitionConstants.UAF_ServiceConnector)),
    SERVICE_CONTROL_FLOW(22, UMLDefinitionConstants.ControlFlow, Collections.singletonList(UMLDefinitionConstants.UAF_ServiceControlFlow)),
    SERVICE_OBJECT_FLOW(23, UMLDefinitionConstants.ObjectFlow, Collections.singletonList(UMLDefinitionConstants.UAF_ServiceObjectFlow)),
    ;

    private final Integer code;

    private final String metaClass;

    private final List<String> stereotype;

    @NotNull
    public static Map<Integer, RelationshipEnum> getRelationshipByCode(@Nullable List<Integer> codes) {
        return Optional.ofNullable(codes)
                .filter(CollectionUtils::isNotEmpty)
                .map(e -> {
                    Map<Integer, RelationshipEnum> map = new HashMap<>();
                    e.forEach(k ->
                            Arrays.stream(RelationshipEnum.values())
                                    .filter(p -> Objects.equals(p.code, k))
                                    .findFirst()
                                    .ifPresent(p -> map.put(p.getCode(), p))
                    );
                    return map;
                }).orElse(Collections.emptyMap());
    }

    public static boolean isConnector(Integer code) {
        return Stream.of(CONNECTOR, BINDING_CONNECTOR, ARBITRARY_CONNECTOR, OPERATIONAL_CONNECTOR, RESOURCE_CONNECTOR, SERVICE_CONNECTOR)
                .map(RelationshipEnum::getCode)
                .anyMatch(e -> Objects.equals(e, code));
    }
}
